import type { AstroIntegration } from 'astro';
import * as pf from 'pagefind'
import { rc } from '../BuildSearchIndex';
import debounce from 'lodash/debounce';
import * as chokidar from 'chokidar'

const contentPath = `src/content`

// clean up
process.on("exit", pf.close)

async function buildIndex(index: pf.PagefindIndex) {
  const res = await rc(contentPath, 0, false)
  await Promise.all(res.map((item) => index.addCustomRecord({
    url: item.link,
    content: `${item.title}-${item.subTitle || ""}-${item.id}-${item.type}`,
    // we only support zh-cn
    language: "zh-cn",
    meta: {
      ...item
    },
    filters: {
      tags: [item.type]
    }
  })))
  await index.writeFiles({
    outputPath: ".cache/pagefind/lib"
  })
}

async function createPFIndex() {
  const pfRes = await pf.createIndex({
    logfile: ".cache/pagefind/pagefind.log",
  })
  if (pfRes.errors.length) {
    throw pfRes.errors
  }
  return pfRes.index as pf.PagefindIndex
}

const debounceBuildIndex = debounce(buildIndex, 500)

export default function BuildPagefind(): AstroIntegration {
  return {
    name: "BuildPagefind",
    hooks: {
      async "astro:server:start"({ logger }) {
        // development will build index by old search index integration
        if (process.env.NODE_ENV === 'development') {
          logger.info("开发环境下搜索引擎的结果与生产环境会有不同呈现！")

          let index: pf.PagefindIndex
          try {
            index = await createPFIndex()
          } catch (e: any) {
            e.forEach((error: string) => logger.error(error))
            return
          }

          chokidar
            .watch(contentPath, {
              persistent: true,
              depth: 99, // 监听深度
            })
            .on("all", (_, path) => {
              if (path.endsWith(".md") || path.endsWith(".mdx"))
                debounceBuildIndex(index)
            })

          logger.info("Pagefind dev build success")
        }
      },
      async "astro:build:done"({ logger }) {
        logger.info("生产环境构建搜索集成中...")
        let index: pf.PagefindIndex
        // build old search index so it can provide search result `type`
        await rc(contentPath)

        try {
          index = await createPFIndex()
        } catch (e: any) {
          e.forEach((error: string) => logger.error(error))
          return
        }

        await index.addDirectory({
          path: "dist"
        })

        await index.writeFiles({
          outputPath: "dist/pagefind"
        })

        logger.info("Pagefind production build success")
      }
    }
  }
}